package com.order.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.common.context.UserContextHolder;
import com.common.domain.Pages.PageResult;
import com.common.tool.StringTool;
import com.google.common.util.concurrent.AtomicDouble;
import com.order.domain.dto.OrderEvaluateDto;
import com.order.domain.dto.OrderReviewDto;
import com.order.domain.dto.OrderReviewPageParams;
import com.order.domain.pojo.*;
import com.order.domain.vo.OrderReviewPageVo;
import com.order.domain.vo.OrderReviewVo;
import com.order.enums.OrderReviewStatus;
import com.order.feign.CourseFeignClient;
import com.order.feign.MediaFeignClient;
import com.order.feign.UserFeignClient;
import com.order.mapper.OrderReviewMapper;
import com.order.service.IOrderDetailService;
import com.order.service.IOrderReviewDetailService;
import com.order.service.IOrderReviewService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import eu.bitwalker.useragentutils.UserAgent;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * <p>
 * 订单评论主表 服务实现类
 * </p>
 *
 * @author 小杰大人
 * @since 2025-10-09
 */
@Service
public class OrderReviewServiceImpl extends ServiceImpl<OrderReviewMapper, OrderReview> implements IOrderReviewService {

    @Resource
    IOrderReviewDetailService iOrderReviewDetailService;

    @Resource
    IOrderDetailService iOrderDetailService;

    @Resource
    UserFeignClient userFeignClient;

    @Resource
    CourseFeignClient courseFeignClient;

    @Resource
    MediaFeignClient mediaFeignClient;

    @Override
    public OrderReviewPageVo pageList(OrderReviewPageParams orderReviewPageParams) {
        List<OrderReviewDto> pageres = baseMapper.pageList(orderReviewPageParams.getPageOn(),orderReviewPageParams.getPageSize(),orderReviewPageParams.getCourseId(),orderReviewPageParams.getMaxRating());
        Set<Long> ids = new HashSet<>();
        for (OrderReviewDto orderReviewDto : pageres) {
            ids.add(orderReviewDto.getUserId());
        }
        Map<Long, UserInfo> data = userFeignClient.querySelectUserListByIds(new ArrayList<>(ids)).getData();
        AtomicDouble totalScore = new AtomicDouble(0);
        AtomicInteger goodCount = new AtomicInteger(0);
        List<OrderReviewPageVo.OrderReviewPageDetailVo> list = pageres.stream()
                .map(
                orderReviewDto -> {
                    OrderReviewPageVo.OrderReviewPageDetailVo orderReviewPageDetailVo = new OrderReviewPageVo.OrderReviewPageDetailVo();
                    BeanUtils.copyProperties(orderReviewDto,orderReviewPageDetailVo);
                    totalScore.addAndGet(orderReviewPageDetailVo.getRating().doubleValue());
                    if (orderReviewPageDetailVo.getRating().doubleValue() > 4.0){
                        goodCount.incrementAndGet();
                    }
                    orderReviewPageDetailVo.setCreateTime(orderReviewDto.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                    UserInfo userInfo = data.get(orderReviewDto.getUserId());
                    orderReviewPageDetailVo.setUserAvatar(userInfo.getImage());
                    orderReviewPageDetailVo.setUserName(userInfo.getUsername());
                    String mediaIds = orderReviewDto.getMediaIds();
                    if (!StrUtil.isEmptyIfStr(mediaIds)){
                        Collection<Media> values = mediaFeignClient.querySelectMediaByIds(StringTool.convertIdsToList(mediaIds)).getData().values();
                        List<String> previews = values.stream().map(Media::getUrl).toList();
                        orderReviewPageDetailVo.setPreviews(previews);
                    }
                    return orderReviewPageDetailVo;
                }
        ).toList();
        OrderReviewPageVo orderReviewPageVo = new OrderReviewPageVo();
        orderReviewPageVo.setDetails(list);
        // 计算综合评分（满分100，不保留小数）
        int totalCount = list.size();
        int comprehensiveScore = totalCount > 0 ?
                (int) Math.round((totalScore.get() / totalCount) * 20) : 0;
        orderReviewPageVo.setScore(comprehensiveScore);
        // 计算好评率并返回整数字符串格式
        int goodCountValue = goodCount.get();
        String goodRate;
        if (totalCount > 0) {
            int rate = (goodCountValue * 100) / totalCount;
            goodRate = rate + "%";
        } else {
            goodRate = "0%";
        }
        orderReviewPageVo.setGoodRate(goodRate);
        orderReviewPageVo.setTotalCount(totalCount);
        return orderReviewPageVo;
    }

    @Override
    public OrderReviewVo review(Long orderId) {
        OrderReviewVo orderReviewVo = new OrderReviewVo();
        OrderDetail orderDetail = iOrderDetailService.getOne(new LambdaQueryWrapper<OrderDetail>().eq(OrderDetail::getOrderId, orderId));
        BeanUtils.copyProperties(orderDetail,orderReviewVo);
        UserInfo userInfo = userFeignClient.querySelectUserInfoById(orderDetail.getUserId()).getData();
        Course course = courseFeignClient.getCourseInfoByUniqueIdentification(orderDetail.getCourseId()).getData();
        orderReviewVo.setUserAvatar(userInfo.getImage());
        orderReviewVo.setBuyCount(course.getSales());
        orderReviewVo.setRating(course.getScore());
        orderReviewVo.setCreateTime(orderDetail.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        orderReviewVo.setId(orderId);
        return orderReviewVo;
    }

    @Override
    @Transactional
    public void evaluate(OrderEvaluateDto orderEvaluateDto, HttpServletRequest httpServletRequest) {
        // 获取用户IP地址
        String clientIp = getClientIpAddress(httpServletRequest);
        // 获取设备信息
        String deviceInfo = parseDeviceInfo(httpServletRequest);
        OrderReview orderReview = new OrderReview();
        orderReview.setOrderId(orderEvaluateDto.getOrderId());
        orderReview.setOrderNo(orderEvaluateDto.getOrderNo());
        orderReview.setUserId(UserContextHolder.getContext().getUsersId());
        orderReview.setMediaIds(orderEvaluateDto.getMediaIds());
        orderReview.setIsAnonymous(orderEvaluateDto.getIsAnonymous());
        orderReview.setStatus(OrderReviewStatus.REVIEWED.getCode());
        orderReview.setIsTop((byte) 0);
        orderReview.setIpAddress(clientIp);
        orderReview.setDeviceInfo(deviceInfo);
        if (!this.save(orderReview)) {
            throw new RuntimeException("保存评价详情失败");
        }
        OrderReviewDetail orderReviewDetail = new OrderReviewDetail();
        orderReviewDetail.setReviewId(orderReview.getId());
        orderReviewDetail.setOrderId(orderReview.getOrderId());
        orderReviewDetail.setOrderNo(orderReview.getOrderNo());
        orderReviewDetail.setCourseId(orderEvaluateDto.getCourseId());
        orderReviewDetail.setRating(orderEvaluateDto.getRating());
        orderReviewDetail.setContent(orderEvaluateDto.getContent());
        orderReviewDetail.setIsRecommend((byte) 0);
        if (!iOrderReviewDetailService.save(orderReviewDetail)) {
            throw new RuntimeException("保存评价详情失败");
        }
        // 更新课程评分
    }
    private String parseDeviceInfo(HttpServletRequest httpServletRequest) {
        // 获取设备信息
        String userAgentString = httpServletRequest.getHeader("User-Agent");
        UserAgent userAgent = UserAgent.parseUserAgentString(userAgentString);
        return userAgent.getOperatingSystem() + " - " + userAgent.getBrowser();
    }
    private String getClientIpAddress(HttpServletRequest request) {
        String xForwardedFor = request.getHeader("X-Forwarded-For");
        if (xForwardedFor != null && !xForwardedFor.isEmpty() && !"unknown".equalsIgnoreCase(xForwardedFor)) {
            return xForwardedFor.split(",")[0];
        }

        String xRealIp = request.getHeader("X-Real-IP");
        if (xRealIp != null && !xRealIp.isEmpty() && !"unknown".equalsIgnoreCase(xRealIp)) {
            return xRealIp;
        }
        return request.getRemoteAddr();
    }

    @Override
    public Boolean isReviewed(Long orderId,Long userId) {
        return this.getOne(new LambdaQueryWrapper<OrderReview>().eq(OrderReview::getOrderId, orderId).eq(OrderReview::getUserId, userId)) != null;
    }
}
